home *** CD-ROM | disk | FTP | other *** search
/ Aminet 34 / Aminet 34 (2000)(Schatztruhe)[!][Dec 1999].iso / Aminet / util / gnu / unixcmds.lha / unixcmds / src / uniq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-06  |  4.7 KB  |  217 lines

  1. /* FUNCTIONS
  2. This source file includes following functions.
  3. xfopen
  4. main
  5. skip
  6. equal
  7. show
  8. uniq
  9. usage
  10. getline
  11. */
  12.  
  13. /* uniq - compact repeated lines                Author: John Woods */
  14. /* Uniq [-udc] [-n] [+n] [infile [outfile]]
  15.  *
  16.  *      Written 02/08/86 by John Woods, placed into public domain.  Enjoy.
  17.  *
  18.  */
  19.  
  20. /* If the symbol WRITE_ERROR is defined, uniq will exit(1) if it gets a
  21.  * write error on the output.  This is not (of course) how V7 uniq does it,
  22.  * so undefine the symbol if you want to lose your output to a full disk
  23.  */
  24.  
  25. #define WRITE_ERROR 1
  26. #include <ctype.h>
  27. #include <errno.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31.  
  32. char buffer[BUFSIZ];
  33. int uflag = 1;                  /* default is union of -d and -u outputs */
  34. int dflag = 1;                  /* flags are mutually exclusive */
  35. int cflag = 0;
  36. int fields = 0;
  37. int chars = 0;
  38.  
  39. int main  (int argc, char **argv);
  40. FILE *xfopen  (char *fn, char *mode);
  41. char *skip  (char *s);
  42. int equal  (char *s1, char *s2);
  43. void show  (char *line, int count);
  44. int uniq  (void);
  45. void usage  (void);
  46. int getline  (char *buf, int count);
  47.  
  48. FILE *xfopen(fn, mode)
  49. /* [<][>][^][v][top][bottom][index][help] */
  50. char *fn, *mode;
  51. {
  52.   FILE *p;
  53.  
  54.   if ((p = fopen(fn, mode)) == NULL) {
  55.         perror("uniq");
  56.         fflush(stdout);
  57.         exit(1);
  58.   }
  59.   return(p);
  60. }
  61.  
  62. int main(argc, argv)
  63. /* [<][>][^][v][top][bottom][index][help] */
  64. int argc;
  65. char *argv[];
  66. {
  67.   char *p;
  68.   int inf = -1, outf;
  69.  
  70.   setbuf(stdout, buffer);
  71.   for (--argc, ++argv; argc > 0 && (**argv == '-' || **argv == '+');
  72.        --argc, ++argv) {
  73.         if (**argv == '+')
  74.                 chars = atoi(*argv + 1);
  75.         else if (isdigit(argv[0][1]))
  76.                 fields = atoi(*argv + 1);
  77.         else if (argv[0][1] == '\0')
  78.                 inf = 0;        /* - is stdin */
  79.         else
  80.                 for (p = *argv + 1; *p; p++) {
  81.                         switch (*p) {
  82.                             case 'd':
  83.                                 dflag = 1;
  84.                                 uflag = 0;
  85.                                 break;
  86.                             case 'u':
  87.                                 uflag = 1;
  88.                                 dflag = 0;
  89.                                 break;
  90.                             case 'c':   cflag = 1;      break;
  91.                             default:    usage();
  92.                         }
  93.                 }
  94.   }
  95.  
  96.   /* Input file */
  97.   if (argc == 0)
  98.         inf = 0;
  99.   else if (inf == -1) {         /* if - was not given */
  100.         fclose(stdin);
  101.         xfopen(*argv++, "r");
  102.         argc--;
  103.   }
  104.   if (argc == 0)
  105.         outf = 1;
  106.   else {
  107.         fclose(stdout);
  108.         xfopen(*argv++, "w");
  109.         argc--;
  110.   }
  111.  
  112.   uniq();
  113.   fflush(stdout);
  114.   return(0);
  115. }
  116.  
  117. char *skip(s)
  118. /* [<][>][^][v][top][bottom][index][help] */
  119. char *s;
  120. {
  121.   int n;
  122.  
  123.   /* Skip fields */
  124.   for (n = fields; n > 0; --n) {
  125.         /* Skip blanks */
  126.         while (*s && (*s == ' ' || *s == '\t')) s++;
  127.         if (!*s) return s;
  128.         while (*s && (*s != ' ' && *s != '\t')) s++;
  129.         if (!*s) return s;
  130.   }
  131.  
  132.   /* Skip characters */
  133.   for (n = chars; n > 0; --n) {
  134.         if (!*s) return s;
  135.         s++;
  136.   }
  137.   return s;
  138. }
  139.  
  140. int equal(s1, s2)
  141. /* [<][>][^][v][top][bottom][index][help] */
  142. char *s1, *s2;
  143. {
  144.   return !strcmp(skip(s1), skip(s2));
  145. }
  146.  
  147. void show(line, count)
  148. /* [<][>][^][v][top][bottom][index][help] */
  149. char *line;
  150. int count;
  151. {
  152.   if (cflag)
  153.         printf("%4d %s", count, line);
  154.   else {
  155.         if ((uflag && count == 1) || (dflag && count != 1))
  156.                 printf("%s", line);
  157.   }
  158. }
  159.  
  160. /* The meat of the whole affair */
  161. char *nowline, *prevline, buf1[1024], buf2[1024];
  162.  
  163. int uniq()
  164. /* [<][>][^][v][top][bottom][index][help] */
  165. {
  166.   char *p;
  167.   int seen;
  168.  
  169.   /* Setup */
  170.   prevline = buf1;
  171.   if (getline(prevline, 1024) < 0) return(0);
  172.   seen = 1;
  173.   nowline = buf2;
  174.  
  175.   /* Get nowline and compare if not equal, dump prevline and swap
  176.    * pointers else continue, bumping seen count */
  177.   while (getline(nowline, 1024) > 0) {
  178.         if (!equal(prevline, nowline)) {
  179.                 show(prevline, seen);
  180.                 seen = 1;
  181.                 p = nowline;
  182.                 nowline = prevline;
  183.                 prevline = p;
  184.         } else
  185.                 seen += 1;
  186.   }
  187.   show(prevline, seen);
  188.   return 0;
  189. }
  190.  
  191. void usage()
  192. /* [<][>][^][v][top][bottom][index][help] */
  193. {
  194.   fprintf(stderr, "Usage: uniq [-udc] [+n] [-n] [input [output]]\n");
  195. }
  196.  
  197. int getline(buf, count)
  198. /* [<][>][^][v][top][bottom][index][help] */
  199. char *buf;
  200. int count;
  201. {
  202.   int c;
  203.   int ct = 0;
  204.  
  205.   while (ct++ < count) {
  206.         c = getc(stdin);
  207.         if (c < 0) return(-1);
  208.         *buf++ = c;
  209.         if (c == '\n') {
  210.                 *buf++ = 0;
  211.                 return(ct);
  212.         }
  213.   }
  214.   return(ct);
  215. }
  216. /* [<][>][^][v][top][bottom][index][help] */
  217.